/**
 * @(#)RetentTaskServiceImpl.java 2016年11月7日
 * Copyright(C) 2016 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service.impl;

import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.domian.channel.RetentRecordVo;
import org.jsbd.boss.domian.channel.RetentTaskVo;
import org.jsbd.boss.service.IRetentTaskService;
import org.jsbd.boss.service.ITaskPoolService;
import org.jsbd.boss.task.RetentBrushUpdateTask;
import org.jsbd.boss.task.RetentDataPoolTask;
import org.jsbd.boss.task.RetentQueueTask;
import org.jsbd.boss.task.RetentUpdateTask;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 留存任务
 *
 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
 * @version 1.0.0
 */
@Service("retentTaskService")
public class RetentTaskServiceImpl implements IRetentTaskService {
    public static final Logger LOGGER = LoggerFactory.getLogger(RetentTaskServiceImpl.class);

    @Resource
    private RedisClient redisClient;

    @Resource
    private RedisClient redisClientTemp;

    @Resource
    private TaskLuaManager taskLuaManager;


    @Resource
    private ITaskPoolService taskPoolService;

    /**
     * getRetentTaskKey:留存任务key
     *
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    private String getRetentTaskHashKey(String mark) {
        return CacheKey.AR_TASK2 + DateUtil.getDaysOfTime() + mark;
    }




    @Override
    public boolean syncTask(Object taskVo) throws Exception {
        RetentTaskVo taskInfo = (RetentTaskVo) taskVo;
        String orderId = taskInfo.getOrderId();
        if (!redisClientTemp.evalSetNx(orderId, 180)) {
            return false;
        }
        taskPoolService.exec(new RetentUpdateTask(taskInfo));
        return true;
    }


    @Override
    public boolean syncBrushTask(Object taskVo) throws Exception {
        RetentTaskVo taskInfo = (RetentTaskVo) taskVo;
        taskPoolService.exec(new RetentBrushUpdateTask(taskInfo));
        return true;
    }



    @Override
    public void updateTaskQueue() {
        updateRetentTask(2);
    }

    private void updateRetentTask(int taskType) {
        Set<String> apkSet = (Set<String>) redisClient.get(CacheKey.VERR_APK_KEY3);
        if (apkSet == null || apkSet.isEmpty()) {
            return;
        }

        if (!redisClient.evalSetNx(CacheKey.RETENT_TASK_QUEUE_LOCK + taskType, 5)) {
            return;
        }

        for (String apk : apkSet) {
            String retentDayKey = CacheKey.AR_TASK_DAY3 + apk;
            List<RetentRecordVo> retentList = (List<RetentRecordVo>) redisClient.get(retentDayKey);
            if (retentList != null && retentList.size() > 0) {
                if (taskType == 1) {
                    taskPoolService.execRetentPoolTask(new RetentDataPoolTask(retentList));
                } else {
                    taskPoolService.execRetentQueueTask(new RetentQueueTask(retentList));
                }
            }
        }
    }


    @Override
    public void updateTaskOfCache() {
        updateRetentTask(1);
    }

    @Override
    public Integer[] getLeftTaskNum(String[] marks) throws Exception {
        if (marks != null) {
            List<String> keys = new ArrayList<String>();
            for (int i = 0; i < marks.length; i++) {
                keys.add(getRetentTaskHashKey(marks[i]));
            }
            return taskLuaManager.getLeftTaskNum(keys).toArray(new Integer[0]);
        }
        return null;
    }

    @Override
    public String[] hasDoNum(List<String> marks) {
        StringBuilder sb = new StringBuilder();
        sb.append("local result={} local j=1");
        sb.append(" for i=1,#KEYS do");
        sb.append(" local total=redis.call('hget', KEYS[i], 'total')");
        sb.append(" local exectotal=redis.call('hget', KEYS[i], 'exectotal')");
        sb.append(" result[j]=total result[j+1]=exectotal j=j+2  end return result");
        String[] sizes = null;
        if (marks != null) {
            String[] keys = new String[marks.size()];
            for (int i = 0; i < marks.size(); i++) {
                String mark = marks.get(i);
                keys[i] = getRetentTaskHashKey(mark);
            }
            Object retult = redisClient.eval(sb.toString(), ReturnType.MULTI, keys);
            if (retult != null) {
                List numList = (List) retult;
                sizes = new String[numList.size() / 2];
                for (int i = 0, j = 0; i < numList.size(); i = i + 2, j++) {
                    String totalStr = "0";
                    String execTotalStr = "0";
                    byte[] total = (byte[]) numList.get(i);
                    byte[] execTotal = (byte[]) numList.get(i + 1);
                    if (total != null) {
                        totalStr = new String(total);
                    }
                    if (execTotal != null) {
                        execTotalStr = new String(execTotal);
                    }
                    sizes[j] = totalStr + "|" + execTotalStr;
                }
            }
        }
        return sizes;

    }

}